import { Injectable, Logger } from '@nestjs/common';
import { MappingType, DataType } from '../../database/entities/copilot-types';
import { FieldChange } from './copilot-request-logger.service';

export interface DiffOptions {
  maxDepth?: number;
  ignoredFields?: string[];
  sensitiveFields?: string[];
  arrayOrderSensitive?: boolean;
}

export interface FieldDiff {
  fieldPath: string;
  mappingType: MappingType;
  fromValue?: any;
  toValue?: any;
  fromFieldName?: string;
  toFieldName?: string;
  fromType?: DataType;
  toType?: DataType;
}

@Injectable()
export class FieldDiffTrackerService {
  private readonly logger = new Logger(FieldDiffTrackerService.name);

  /**
   * 比较两个对象，生成字段变化列表
   */
  compareObjects(
    fromObj: any,
    toObj: any,
    options: DiffOptions = {},
    basePath: string = ''
  ): FieldChange[] {
    const {
      maxDepth = 10,
      ignoredFields = [],
      sensitiveFields = [],
      arrayOrderSensitive = true
    } = options;

    const changes: FieldChange[] = [];

    try {
      // 如果对象为空或null，进行特殊处理
      if (fromObj === null && toObj === null) return changes;
      if (fromObj === null && toObj !== null) {
        return this.handleObjectCreation(toObj, basePath);
      }
      if (fromObj !== null && toObj === null) {
        return this.handleObjectDeletion(fromObj, basePath);
      }

      // 获取所有键的并集
      const allKeys = new Set([
        ...Object.keys(fromObj || {}),
        ...Object.keys(toObj || {})
      ]);

      for (const key of allKeys) {
        const currentPath = basePath ? `${basePath}.${key}` : key;
        
        // 跳过忽略的字段
        if (ignoredFields.includes(key) || ignoredFields.includes(currentPath)) {
          continue;
        }

        const fromValue = fromObj?.[key];
        const toValue = toObj?.[key];

        // 字段被添加
        if (fromValue === undefined && toValue !== undefined) {
          changes.push({
            fieldPath: currentPath,
            mappingType: MappingType.FIELD_ADDED,
            toFieldName: key,
            toValue: toValue,
            transformationRule: `添加新字段: ${key}`
          });
          continue;
        }

        // 字段被移除
        if (fromValue !== undefined && toValue === undefined) {
          changes.push({
            fieldPath: currentPath,
            mappingType: MappingType.FIELD_REMOVED,
            fromFieldName: key,
            fromValue: fromValue,
            transformationRule: `移除字段: ${key}`
          });
          continue;
        }

        // 字段值存在，比较差异
        if (fromValue !== undefined && toValue !== undefined) {
          const fieldChanges = this.compareFieldValues(
            fromValue,
            toValue,
            currentPath,
            key,
            options,
            maxDepth - 1
          );
          changes.push(...fieldChanges);
        }
      }

      return changes;
    } catch (error) {
      this.logger.error(`Error comparing objects: ${error.message}`);
      return [];
    }
  }

  /**
   * 比较字段值
   */
  private compareFieldValues(
    fromValue: any,
    toValue: any,
    path: string,
    fieldName: string,
    options: DiffOptions,
    remainingDepth: number
  ): FieldChange[] {
    const changes: FieldChange[] = [];

    // 检查数据类型是否变化
    const fromType = this.detectDataType(fromValue);
    const toType = this.detectDataType(toValue);

    if (fromType !== toType) {
      changes.push({
        fieldPath: path,
        mappingType: MappingType.TYPE_CHANGED,
        fromFieldName: fieldName,
        toFieldName: fieldName,
        fromValue: fromValue,
        toValue: toValue,
        transformationRule: `数据类型变更: ${fromType} -> ${toType}`
      });
      return changes;
    }

    // 基本类型比较
    if (this.isPrimitiveType(fromValue) && this.isPrimitiveType(toValue)) {
      if (fromValue !== toValue) {
        changes.push({
          fieldPath: path,
          mappingType: MappingType.VALUE_TRANSFORMED,
          fromFieldName: fieldName,
          toFieldName: fieldName,
          fromValue: fromValue,
          toValue: toValue,
          transformationRule: `值变更: ${fromValue} -> ${toValue}`
        });
      }
      return changes;
    }

    // 数组比较
    if (Array.isArray(fromValue) && Array.isArray(toValue)) {
      const arrayChanges = this.compareArrays(
        fromValue,
        toValue,
        path,
        fieldName,
        options,
        remainingDepth
      );
      changes.push(...arrayChanges);
      return changes;
    }

    // 对象比较（递归）
    if (this.isObject(fromValue) && this.isObject(toValue)) {
      if (remainingDepth > 0) {
        const nestedChanges = this.compareObjects(
          fromValue,
          toValue,
          options,
          path
        );
        changes.push(...nestedChanges);
      } else {
        // 达到最大深度，标记为结构变化
        if (!this.deepEqual(fromValue, toValue)) {
          changes.push({
            fieldPath: path,
            mappingType: MappingType.STRUCTURE_CHANGED,
            fromFieldName: fieldName,
            toFieldName: fieldName,
            fromValue: this.truncateDeepObject(fromValue),
            toValue: this.truncateDeepObject(toValue),
            transformationRule: '复杂对象结构变更（已达最大比较深度）'
          });
        }
      }
      return changes;
    }

    // 其他情况，标记为值变更
    if (!this.deepEqual(fromValue, toValue)) {
      changes.push({
        fieldPath: path,
        mappingType: MappingType.VALUE_TRANSFORMED,
        fromFieldName: fieldName,
        toFieldName: fieldName,
        fromValue: fromValue,
        toValue: toValue,
        transformationRule: `复杂值变更`
      });
    }

    return changes;
  }

  /**
   * 比较数组
   */
  private compareArrays(
    fromArray: any[],
    toArray: any[],
    path: string,
    fieldName: string,
    options: DiffOptions,
    remainingDepth: number
  ): FieldChange[] {
    const changes: FieldChange[] = [];

    // 数组长度变化
    if (fromArray.length !== toArray.length) {
      changes.push({
        fieldPath: `${path}.length`,
        mappingType: MappingType.FIELD_MODIFIED,
        fromFieldName: `${fieldName}.length`,
        toFieldName: `${fieldName}.length`,
        fromValue: fromArray.length,
        toValue: toArray.length,
        transformationRule: `数组长度变更: ${fromArray.length} -> ${toArray.length}`
      });
    }

    // 如果不关心数组顺序，先排序
    let sortedFromArray = fromArray;
    let sortedToArray = toArray;
    
    if (!options.arrayOrderSensitive) {
      sortedFromArray = [...fromArray].sort((a, b) => 
        JSON.stringify(a).localeCompare(JSON.stringify(b))
      );
      sortedToArray = [...toArray].sort((a, b) => 
        JSON.stringify(a).localeCompare(JSON.stringify(b))
      );
    }

    // 比较数组元素
    const maxLength = Math.max(sortedFromArray.length, sortedToArray.length);
    
    for (let i = 0; i < maxLength; i++) {
      const currentPath = `${path}[${i}]`;
      const fromItem = sortedFromArray[i];
      const toItem = sortedToArray[i];

      if (fromItem === undefined && toItem !== undefined) {
        changes.push({
          fieldPath: currentPath,
          mappingType: MappingType.FIELD_ADDED,
          toFieldName: `${fieldName}[${i}]`,
          toValue: toItem,
          transformationRule: `数组新增元素 [${i}]`
        });
      } else if (fromItem !== undefined && toItem === undefined) {
        changes.push({
          fieldPath: currentPath,
          mappingType: MappingType.FIELD_REMOVED,
          fromFieldName: `${fieldName}[${i}]`,
          fromValue: fromItem,
          transformationRule: `数组移除元素 [${i}]`
        });
      } else if (fromItem !== undefined && toItem !== undefined) {
        const itemChanges = this.compareFieldValues(
          fromItem,
          toItem,
          currentPath,
          `${fieldName}[${i}]`,
          options,
          remainingDepth
        );
        changes.push(...itemChanges);
      }
    }

    return changes;
  }

  /**
   * 处理对象创建
   */
  private handleObjectCreation(obj: any, basePath: string): FieldChange[] {
    const changes: FieldChange[] = [];
    
    if (this.isPrimitiveType(obj)) {
      changes.push({
        fieldPath: basePath,
        mappingType: MappingType.FIELD_ADDED,
        toValue: obj,
        transformationRule: '创建新值'
      });
    } else if (this.isObject(obj)) {
      for (const [key, value] of Object.entries(obj)) {
        const currentPath = basePath ? `${basePath}.${key}` : key;
        const nestedChanges = this.handleObjectCreation(value, currentPath);
        changes.push(...nestedChanges);
      }
    }
    
    return changes;
  }

  /**
   * 处理对象删除
   */
  private handleObjectDeletion(obj: any, basePath: string): FieldChange[] {
    const changes: FieldChange[] = [];
    
    if (this.isPrimitiveType(obj)) {
      changes.push({
        fieldPath: basePath,
        mappingType: MappingType.FIELD_REMOVED,
        fromValue: obj,
        transformationRule: '删除值'
      });
    } else if (this.isObject(obj)) {
      for (const [key, value] of Object.entries(obj)) {
        const currentPath = basePath ? `${basePath}.${key}` : key;
        const nestedChanges = this.handleObjectDeletion(value, currentPath);
        changes.push(...nestedChanges);
      }
    }
    
    return changes;
  }

  /**
   * 检测数据类型
   */
  private detectDataType(value: any): DataType {
    if (value === null) return DataType.NULL;
    if (value === undefined) return DataType.UNDEFINED;
    if (typeof value === 'string') return DataType.STRING;
    if (typeof value === 'number') return DataType.NUMBER;
    if (typeof value === 'boolean') return DataType.BOOLEAN;
    if (Array.isArray(value)) return DataType.ARRAY;
    if (typeof value === 'object') return DataType.OBJECT;
    return DataType.STRING;
  }

  /**
   * 判断是否为基本类型
   */
  private isPrimitiveType(value: any): boolean {
    return value === null || 
           value === undefined || 
           typeof value === 'string' || 
           typeof value === 'number' || 
           typeof value === 'boolean';
  }

  /**
   * 判断是否为对象
   */
  private isObject(value: any): boolean {
    return value !== null && typeof value === 'object' && !Array.isArray(value);
  }

  /**
   * 深度比较两个对象是否相等
   */
  private deepEqual(a: any, b: any): boolean {
    try {
      return JSON.stringify(a) === JSON.stringify(b);
    } catch {
      return a === b;
    }
  }

  /**
   * 截断深层对象以避免过大的存储
   */
  private truncateDeepObject(obj: any, maxKeys: number = 5): any {
    if (!this.isObject(obj)) return obj;
    
    const keys = Object.keys(obj);
    if (keys.length <= maxKeys) return obj;
    
    const truncated: any = {};
    for (let i = 0; i < maxKeys; i++) {
      truncated[keys[i]] = obj[keys[i]];
    }
    truncated['...'] = `[省略 ${keys.length - maxKeys} 个字段]`;
    
    return truncated;
  }

  /**
   * 分析API转换的常见模式
   */
  analyzeTransformationPattern(changes: FieldChange[]): {
    pattern: string;
    description: string;
    confidence: number;
  } {
    if (changes.length === 0) {
      return { pattern: 'no_change', description: '无变化', confidence: 1.0 };
    }

    const patterns = {
      field_rename: changes.filter(c => c.mappingType === MappingType.FIELD_RENAMED).length,
      value_transform: changes.filter(c => c.mappingType === MappingType.VALUE_TRANSFORMED).length,
      structure_change: changes.filter(c => c.mappingType === MappingType.STRUCTURE_CHANGED).length,
      field_addition: changes.filter(c => c.mappingType === MappingType.FIELD_ADDED).length,
      field_removal: changes.filter(c => c.mappingType === MappingType.FIELD_REMOVED).length,
    };

    const total = Object.values(patterns).reduce((sum, count) => sum + count, 0);
    const dominantPattern = Object.entries(patterns).reduce((max, [pattern, count]) => 
      count > max.count ? { pattern, count } : max, 
      { pattern: 'mixed', count: 0 }
    );

    const confidence = total > 0 ? dominantPattern.count / total : 0;

    const descriptions: Record<string, string> = {
      field_rename: 'API字段重命名转换',
      value_transform: 'API数据值转换',
      structure_change: 'API数据结构重组',
      field_addition: 'API字段扩展',
      field_removal: 'API字段精简',
      mixed: '混合转换模式'
    };

    return {
      pattern: dominantPattern.pattern,
      description: descriptions[dominantPattern.pattern] || '未知转换模式',
      confidence: Math.round(confidence * 100) / 100
    };
  }

  /**
   * 生成字段变化摘要
   */
  generateChangeSummary(changes: FieldChange[]): {
    totalChanges: number;
    addedFields: number;
    removedFields: number;
    modifiedFields: number;
    renamedFields: number;
    typeChanges: number;
    criticalChanges: string[];
  } {
    const summary = {
      totalChanges: changes.length,
      addedFields: 0,
      removedFields: 0,
      modifiedFields: 0,
      renamedFields: 0,
      typeChanges: 0,
      criticalChanges: [] as string[]
    };

    const criticalFields = ['model', 'messages', 'max_tokens', 'temperature', 'stream'];

    for (const change of changes) {
      switch (change.mappingType) {
        case MappingType.FIELD_ADDED:
          summary.addedFields++;
          break;
        case MappingType.FIELD_REMOVED:
          summary.removedFields++;
          break;
        case MappingType.FIELD_MODIFIED:
        case MappingType.VALUE_TRANSFORMED:
          summary.modifiedFields++;
          break;
        case MappingType.FIELD_RENAMED:
          summary.renamedFields++;
          break;
        case MappingType.TYPE_CHANGED:
          summary.typeChanges++;
          break;
      }

      // 检查是否为关键字段变化
      if (criticalFields.some(field => change.fieldPath.toLowerCase().includes(field.toLowerCase()))) {
        summary.criticalChanges.push(change.fieldPath);
      }
    }

    return summary;
  }
}